package proj2;

import java.util.Random;

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.functions.MultilayerPerceptron;
import weka.classifiers.trees.J48;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;

public class Main {

	public static Classifier naiveBayseian(String[] args, int curArg)
			throws Exception {
		NaiveBayes nb = new NaiveBayes();

		String kernelEstimate = null;
		String supervised = null;

		kernelEstimate = args[curArg++];
		supervised = args[curArg++];

		String[] options;
		
		if (kernelEstimate.equalsIgnoreCase("true") && supervised.equalsIgnoreCase("false")) {
			options = new String[] {"-K"};
		} else if (kernelEstimate.equalsIgnoreCase("false") && supervised.equalsIgnoreCase("true")) {
			options = new String[] {"-D"};
		} else {
			options = new String[] {};
		}
		
		System.out.println("#" + args[0] + " " + kernelEstimate + " " + supervised);

		nb.setOptions(options);
		return nb;
	}

	public static Classifier decisionTree(String[] args, int curArg)
			throws Exception {
		J48 nb = new J48();

		boolean prunned = true;

		prunned = (args[curArg].equals("true"));

		String[] options;

		if (prunned) {
			options = new String[] {};
		} else {
			options = new String[] { "-U" };
		}

		System.out.println("#" + args[0] + " " + args[curArg]);

		nb.setOptions(options);
		return nb;

	}

	public static Classifier neuralNetwork(String[] args, int curArg)
			throws Exception {

		String learningRate = null;
		String momentum = null;
		String numberHiddenNeurons = null;
		String numberEpochs = null;

		learningRate = args[curArg++];
		momentum = args[curArg++];
		numberHiddenNeurons = args[curArg++];
		numberEpochs = args[curArg++];

		String[] options = new String[8];
		options[0] = "-L"; // Learning Rate
		options[1] = learningRate;
		options[2] = "-M"; // Momentum
		options[3] = momentum;
		options[4] = "-H"; // Number of hidden layer neurons
		options[5] = numberHiddenNeurons;
		options[6] = "-N"; // Number of epochs
		options[7] = numberEpochs;
		// options[8] = "-S"; // Random seed
		// options[9] = "" + (new Random()).nextInt();

		System.out.println("#" + args[0] + " " + learningRate + " " + momentum + " "
				+ numberHiddenNeurons + " " + numberEpochs);

		MultilayerPerceptron scheme = new MultilayerPerceptron();
		scheme.setOptions(options);
		return scheme;
	}

	public static void main(String[] args) throws Exception {

		DataSource source = new DataSource("letter-recognition.arff");
		Instances data = source.getDataSet();
		data.setClassIndex(0); // Set class: letter

		Classifier scheme = null;

		if (args[0].equals("NN")) {
			scheme = neuralNetwork(args, 2);
		} else if (args[0].equals("NB")) {
			scheme = naiveBayseian(args, 2);
		} else if (args[0].equals("DT")) {
			scheme = decisionTree(args, 2);
		} else {
			throw new RuntimeException(args[0]);
		}
		
		int kFold = Integer.parseInt(args[1]);

		Evaluation eval = new Evaluation(data);
		long before = System.currentTimeMillis();
		eval.crossValidateModel(scheme, data, kFold, new Random());
		long time = System.currentTimeMillis() - before;
		System.out.println(eval.correct() + " " + eval.incorrect() + " "
				+ eval.kappa() + " " + eval.meanAbsoluteError() + " "
				+ eval.rootMeanSquaredError() + " "
				+ eval.relativeAbsoluteError() + " "
				+ eval.rootRelativeSquaredError() + " " + eval.numInstances()
				+ " " + time);
	}
}
